package com.kxmall.common.utils;

import cn.dev33.satoken.stp.StpUtil;
import com.kxmall.common.enums.DeviceType;
import com.kxmall.common.enums.UserType;
import com.kxmall.common.exception.UtilException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * Token工具类
 * 提供基于用户类型和ID的Token获取、验证等通用功能
 *
 * @author kxmall
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TokenUtils {

    /**
     * 根据用户类型和ID获取对应的Token
     * 
     * @param userType 用户类型 (app_user, rider_user, sys_user)
     * @param deviceType 设备类型
     * @param userId 用户ID
     * @return Token值
     */
    public static String getTokenByUserTypeAndId(String userType, DeviceType deviceType, Long userId) {
        try {
            String loginId = userType + ":" + userId;
            
            // 获取用户的Token列表
            List<String> tokenList = StpUtil.getTokenValueListByLoginId(loginId, deviceType.getDevice());
            
            if (tokenList == null || tokenList.isEmpty()) {
                throw new UtilException("用户Token不存在 - 用户: " + loginId + ", 设备: " + deviceType.getDevice());
            }
            
            // 返回最新的Token（通常是列表中的最后一个）
            String latestToken = tokenList.get(tokenList.size() - 1);
            
            log.debug("根据用户类型获取Token - 用户: {}, 设备: {}, Token前缀: {}, Token总数: {}", 
                loginId, deviceType.getDevice(), 
                latestToken.substring(0, Math.min(10, latestToken.length())) + "...",
                tokenList.size());
                
            return latestToken;
            
        } catch (Exception e) {
            log.error("根据用户类型获取Token失败 - 用户类型: {}, 设备: {}, 用户ID: {}, 错误: {}", 
                userType, deviceType.getDevice(), userId, e.getMessage());
            throw new UtilException("Token获取失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取APP用户Token
     * 
     * @param userId 用户ID
     * @return Token值
     */
    public static String getAppUserToken(Long userId) {
        log.debug("获取APP用户Token - 用户ID: {}", userId);
        return getTokenByUserTypeAndId(UserType.APP_USER.getUserType(), DeviceType.APP, userId);
    }

    /**
     * 获取骑手用户Token
     * 
     * @param userId 用户ID
     * @return Token值
     */
    public static String getRiderUserToken(Long userId) {
        log.debug("获取骑手用户Token - 用户ID: {}", userId);
        return getTokenByUserTypeAndId(UserType.RIDER_USER.getUserType(), DeviceType.RIDER, userId);
    }

    /**
     * 获取系统用户Token
     * 
     * @param userId 用户ID
     * @return Token值
     */
    public static String getSysUserToken(Long userId) {
        log.debug("获取系统用户Token - 用户ID: {}", userId);
        return getTokenByUserTypeAndId(UserType.SYS_USER.getUserType(), DeviceType.PC, userId);
    }

    /**
     * 验证Token是否属于指定用户
     * 
     * @param tokenValue Token值
     * @param userType 用户类型
     * @param deviceType 设备类型
     * @param userId 用户ID
     * @return 是否匹配
     */
    public static boolean validateTokenOwnership(String tokenValue, String userType, DeviceType deviceType, Long userId) {
        try {
            String expectedToken = TokenUtils.getTokenByUserTypeAndId(userType, deviceType, userId);
            boolean matches = tokenValue.equals(expectedToken);
            
            log.debug("Token所有权验证 - 用户: {}:{}, 设备: {}, 匹配结果: {}", 
                userType, userId, deviceType.getDevice(), matches);
                
            return matches;
            
        } catch (Exception e) {
            log.error("Token所有权验证失败 - 用户: {}:{}, 设备: {}, 错误: {}", 
                userType, userId, deviceType.getDevice(), e.getMessage());
            return false;
        }
    }

    /**
     * 获取用户的所有Token
     * 
     * @param userType 用户类型
     * @param deviceType 设备类型
     * @param userId 用户ID
     * @return Token列表
     */
    public static List<String> getAllUserTokens(String userType, DeviceType deviceType, Long userId) {
        try {
            String loginId = userType + ":" + userId;
            List<String> tokenList = StpUtil.getTokenValueListByLoginId(loginId, deviceType.getDevice());
            
            log.debug("获取用户所有Token - 用户: {}, 设备: {}, Token数量: {}", 
                loginId, deviceType.getDevice(), tokenList != null ? tokenList.size() : 0);
                
            return tokenList;
            
        } catch (Exception e) {
            log.error("获取用户所有Token失败 - 用户: {}:{}, 设备: {}, 错误: {}", 
                userType, userId, deviceType.getDevice(), e.getMessage());
            throw new UtilException("获取用户Token列表失败: " + e.getMessage(), e);
        }
    }

    /**
     * 检查用户是否有有效Token
     * 
     * @param userType 用户类型
     * @param deviceType 设备类型
     * @param userId 用户ID
     * @return 是否有有效Token
     */
    public static boolean hasValidToken(String userType, DeviceType deviceType, Long userId) {
        try {
            List<String> tokenList = getAllUserTokens(userType, deviceType, userId);
            boolean hasToken = tokenList != null && !tokenList.isEmpty();
            
            log.debug("检查用户Token有效性 - 用户: {}:{}, 设备: {}, 有效Token: {}", 
                userType, userId, deviceType.getDevice(), hasToken);
                
            return hasToken;
            
        } catch (Exception e) {
            log.debug("用户Token有效性检查失败 - 用户: {}:{}, 设备: {}, 错误: {}", 
                userType, userId, deviceType.getDevice(), e.getMessage());
            return false;
        }
    }

    /**
     * 清理用户的过期Token
     * 
     * @param userType 用户类型
     * @param deviceType 设备类型
     * @param userId 用户ID
     * @param maxTokenCount 最大Token数量
     */
    public static void cleanupUserTokens(String userType, DeviceType deviceType, Long userId, int maxTokenCount) {
        try {
            List<String> tokenList = getAllUserTokens(userType, deviceType, userId);
            
            if (tokenList != null && tokenList.size() > maxTokenCount) {
                String loginId = userType + ":" + userId;
                
                // 清理最旧的Token，保留最新的maxTokenCount个
                for (int i = 0; i < tokenList.size() - maxTokenCount; i++) {
                    StpUtil.logoutByTokenValue(tokenList.get(i));
                    log.info("清理旧Token - 用户: {}, Token前缀: {}", 
                        loginId, tokenList.get(i).substring(0, Math.min(10, tokenList.get(i).length())) + "...");
                }
                
                log.info("Token清理完成 - 用户: {}, 清理数量: {}, 保留数量: {}", 
                    loginId, tokenList.size() - maxTokenCount, maxTokenCount);
            }
            
        } catch (Exception e) {
            log.error("清理用户Token失败 - 用户: {}:{}, 设备: {}, 错误: {}", 
                userType, userId, deviceType.getDevice(), e.getMessage());
        }
    }

    /**
     * 构建LoginId
     * 
     * @param userType 用户类型
     * @param userId 用户ID
     * @return LoginId
     */
    public static String buildLoginId(String userType, Long userId) {
        return userType + ":" + userId;
    }

    /**
     * 解析LoginId获取用户ID
     * 
     * @param loginId LoginId
     * @return 用户ID
     */
    public static Long parseUserIdFromLoginId(String loginId) {
        try {
            if (loginId == null || !loginId.contains(":")) {
                throw new UtilException("LoginId格式错误: " + loginId);
            }
            
            String[] parts = loginId.split(":");
            if (parts.length != 2) {
                throw new UtilException("LoginId格式错误: " + loginId);
            }
            
            return Long.parseLong(parts[1]);
            
        } catch (NumberFormatException e) {
            throw new UtilException("LoginId中的用户ID格式错误: " + loginId, e);
        }
    }

    /**
     * 解析LoginId获取用户类型
     * 
     * @param loginId LoginId
     * @return 用户类型
     */
    public static String parseUserTypeFromLoginId(String loginId) {
        if (loginId == null || !loginId.contains(":")) {
            throw new UtilException("LoginId格式错误: " + loginId);
        }
        
        String[] parts = loginId.split(":");
        if (parts.length != 2) {
            throw new UtilException("LoginId格式错误: " + loginId);
        }
        
        return parts[0];
    }

    /**
     * 生成Token摘要信息
     * 
     * @param tokenValue Token值
     * @param userType 用户类型
     * @param deviceType 设备类型
     * @param userId 用户ID
     * @return Token摘要
     */
    public static String generateTokenSummary(String tokenValue, String userType, DeviceType deviceType, Long userId) {
        try {
            String tokenPrefix = tokenValue != null ? tokenValue.substring(0, Math.min(10, tokenValue.length())) + "..." : "null";
            
            return String.format(
                "Token摘要 - 用户: %s:%s, 设备: %s, 前缀: %s",
                userType, userId, deviceType.getDevice(), tokenPrefix
            );
            
        } catch (Exception e) {
            log.error("生成Token摘要异常", e);
            return "Token摘要生成失败";
        }
    }
}
